package source.view;

import source.*;

import javax.imageio.ImageIO;
import javax.swing.*;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;


/**
 * This class is responsible for displaying the gamemap.  it overrides the default
 * JPanel's paintComponent() method to make sure the painted map is always current.
 * 
 * @author Brent Moffit
 * @version 1.3
 *
 */

public class AreaViewport extends JPanel {
	protected static final long serialVersionUID = 1;
	private final int tileSize = 100;
	protected int m_selectedRow, m_selectedCol;
	protected int m_rows, m_cols;
	protected Map m_map;
	
	private PlayerStatus currentPlayer;
	
	//protected DisplayLookupTable m_lookupTable;
	
	private HashMap<Tile, JLabel> tileLookup; /** Maps Tile to its JLabel */
	private HashMap<TerrainType, Icon> terrainIconLookup; /** Icons to be placed on a tile */
	
	/**
	 * The only constructor for an AreaViewport takes a map refrence.  This map
	 * will be used as the data source for the view drawn in the viewport.
	 * 
	 * @param map - the Map object that this AreaViewport will be bound to
	 *
	 */
	public AreaViewport(Map map)
	{
		// call superclass constructor
		super();
		// initialize the class instance variables
		
		m_selectedRow = m_selectedCol = -1;
		m_map = map;
		
		m_rows = map.getDimension().height;
		m_cols = map.getDimension().width;
		
		// initialize swing layout
		
		this.setLayout(new GridLayout(m_rows,m_cols));
		
		//m_lookupTable = new DisplayLookupTable("data\\DisplayLookup.dlt");

		tileLookup = new HashMap<Tile, JLabel>();
		terrainIconLookup = new HashMap<TerrainType, Icon>();
		
		initIconLookup();
	}
	
	/**
	 * This operation can be used to set the currently selected 
	 * square.
	 * @param row - the row of new selection
	 * @parma col - the coloumn of the new selection
	 * @exception java.lang.IndexOutOfBoundsException - thrown when either the row
	 * 		or coloumn is not within the map boundaires.
	 */
	public void setSelected(int row, int col) throws java.lang.IndexOutOfBoundsException
	{
		if(row < m_rows && col < m_cols)
		{
			m_selectedRow = row;
			m_selectedCol = col;
			
			this.update();
		} else
		{
			throw new java.lang.IndexOutOfBoundsException("ILLEGAL SELECTION: (" + row + ", " + col + ") does not exist in the current Map");
		}
	}
	
	public int getSelectedX()
	{
		return m_selectedRow;
	}
	
	public int getSelectedY()
	{
		return m_selectedCol;
	}
	
	/**
	 * This Method will initialize the current map and paint it.
	 * 
	 * @param g - the graphical context for the current application
	 */

	private void init(){
		// Update the map data based on the Map
		JLabel current;
		
		this.removeAll();
		
		for(int j = 0; j < m_rows; j++)
			for(int i = 0; i < m_cols; i++)
			{
				current = new JLabel("", JLabel.CENTER);

				buildLabel(current, i, j);
				
				this.add(current);
				this.tileLookup.put(m_map.getSquare()[i][j], current);
			}
		
		this.validate();
		this.repaint();
	}
	/**
	 * Initializes the IconLookup maps
	 */
	private void initIconLookup(){
		try{
			terrainIconLookup.put(TerrainType.IMPASSABLE, new ImageIcon(ImageIO.read(new File("data"+ File.separator + "Impassable.bmp"))));
			terrainIconLookup.put(TerrainType.NORMAL, new ImageIcon(ImageIO.read(new File("data" + File.separator + "Normal.bmp"))));
			terrainIconLookup.put(TerrainType.PLANET, new ImageIcon(ImageIO.read(new File("data" + File.separator + "Planet.bmp"))));
			terrainIconLookup.put(TerrainType.SLOW, new ImageIcon(ImageIO.read(new File("data" + File.separator + "Slow.bmp"))));
		}
		catch(IOException e){}
	}
	/**
	 * Updates the label.
	 * @param label
	 * @param i
	 * @param j
	 */
	private void buildLabel(JLabel label, int i, int j){
		JLabel current = label;
		String labelText = new String();
		
		if(i == m_selectedRow && j == m_selectedCol)
			current.setBorder(BorderFactory.createLineBorder(Color.BLUE, 3));
		else
			current.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
		
		current.setPreferredSize(new Dimension(tileSize,tileSize));
		
		if(!currentPlayer.isExplored(i,j)){
			current.setText("???");
		}
		else{
			//current.setIcon(terrainIconLookup.get(m_map.getSquare()[i][j].getTerrain().getType()));
			labelText = m_map.getSquare()[i][j].getTerrain().getPicture() + ";";
			
			if(m_map.getSquare()[i][j].getTheItem() != null)
				labelText += m_map.getSquare()[i][j].getTheItem().getPicture() + ";";
			
			if(m_map.getSquare()[i][j].getAreaEffect() != null)
				labelText += m_map.getSquare()[i][j].getAreaEffect().getPicture() + ";";
			
			if(m_map.getSquare()[i][j].getBase() != null) {
				labelText += m_map.getSquare()[i][j].getBase().getPlayer().getID() + ": ";
				labelText += m_map.getSquare()[i][j].getBase().getPicture();
				labelText += ";";
			}
			
			for(int k = 0; k < m_map.getSquare()[i][j].getAllUnits().length; k++)
			{
				labelText += m_map.getSquare()[i][j].getAllUnits()[k].getPlayer().getID() + ": ";
				labelText += m_map.getSquare()[i][j].getAllUnits()[k].getPicture() + ": ";
				labelText += m_map.getSquare()[i][j].getAllUnits()[k].getOrientation();
				
				if(k < m_map.getSquare()[i][j].getAllUnits().length - 1) labelText += ";";
			}
							
			labelText = "<html><p>" + labelText + "</p></html>";
			labelText = labelText.replace(";", "</p><p>");
			
			current.setText(labelText);	
		}
		// TODO: tell whoever needs to that they need to update tiles as dirty
		//m_map.getSquare()[i][j].clearDirty();
	}
	
	/**
	 * Updates the AreaViewport.  Should be called after any action.
	 * This method checks for any dirty tiles and updates them.
	 */
	public void update(){
		if(this.tileLookup.isEmpty()){
			init();
		}
		// Go through each 
		for(int row = 0; row < m_map.getSquare().length; row++){
			for(int col = 0; col < m_map.getSquare()[row].length; col++){
				Tile curTile = m_map.getSquare()[row][col];
				if(curTile.isDirty()){
					JLabel label = tileLookup.get(curTile);
					buildLabel(label,row, col);
				}
			}
		}
		validate();
		repaint();
	}
	
/*	public static void main(String[] args) // debug method
	{
		MainScreen m = new MainScreen(new Map(10,10));
		m.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		m.setVisible(true);
		
		m.switchToAreaViewport();
		
		java.util.Random rand = new java.util.Random();
		int row, col;
		
		
		try
		{
			while(true)
			{
				Thread.sleep(2000);
				row = rand.nextInt(10);
				col = rand.nextInt(10);
				m.getAreaViewport().setSelected(row, col);
				MainScreen.writeToConsole("AreaViewport: (" + row + ", " + col + ") Selected");
			}
		}
		catch(InterruptedException e)
		{
			System.err.println(e.toString());
		}
	}
	*/
	public int getTileSize(){
		return tileSize;
	}
	public Dimension getDimension(){
		return new Dimension(m_rows, m_cols);
	}
	
	public void setCurrentPlayer(PlayerStatus currentPlayer){
		this.currentPlayer = currentPlayer;
	}
}
